home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
ATARI_TN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-11
|
8KB
|
355 lines
/* Support routines for TNC2 emulator - Atari ST version */
#ifdef MWC
#include <osbind.h> /* os interface defines */
#endif
#include "global.h"
#include "ax25.h"
#include "timer.h"
#include "slip.h"
#include "tnc2.h"
#define PIPEBUF 512 /* size of a pipe buffer */
#define FLOW_LOW 64 /* low-water mark */
#define FLOW_HIGH 480 /* high-water mark */
#define SYSBASE *((long *) 0x4f2L) /* start of operating system */
static unsigned int biosvers; /* set to BIOS version# */
#define BCONSTAT ((long (**)()) 0x51e) /* Bconstat vector */
#define BCONIN ((long (**)()) 0x53e) /* Bconin vector */
#define BCOSTAT ((long (**)()) 0x55e) /* Bcostat vector */
#define BCONOUT ((void (**)()) 0x57e) /* Bconout vector */
extern char nospace[];
/* routines that simulate a character device to the client */
static struct tnc *dev2tnc[8]; /* tnc struct per device */
static long
pconstat (dev)
int dev;
{
if (dev2tnc[dev]->output.num != 0)
return -1;
return 0;
}
static long
pconin (dev)
int dev;
{
register struct tnc *tnc2;
char c;
tnc2 = dev2tnc[dev];
if (tnc2->output.num == 0)
return TCH_NOCHAR; /* that will fail, but cannot wait */
c = *tnc2->output.out++;
if (tnc2->output.out == tnc2->output.end)
tnc2->output.out = tnc2->output.begin;
if (--(tnc2->output.num) < FLOW_LOW)
tnc2->status &= ~TS_TXSTOP;
return uchar(c);
}
static long
pcostat (dev)
int dev;
{
register struct tnc *tnc2;
tnc2 = dev2tnc[dev];
if (tnc2->input.num != 0 && /* something buffered? */
!(tnc2->status & TS_TXBUF)) /* not allowed to buffer? */
return 0; /* buffer full */
if (tnc2->input.num < FLOW_LOW || /* below flow control treshold? */
(!(tnc2->status & TS_RXSTOP) && tnc2->input.num < FLOW_HIGH))
return -1; /* buffer is not full */
return 0; /* buffer full */
}
static void
pconout (dev,c)
int dev,c;
{
register struct tnc *tnc2;
tnc2 = dev2tnc[dev];
if (tnc2->input.num == PIPEBUF) /* buffer full? */
tnc2->status |= TS_RXOVR; /* then we have an overrun */
else {
*tnc2->input.in++ = c;
if (tnc2->input.in == tnc2->input.end)
tnc2->input.in = tnc2->input.begin;
if (++(tnc2->input.num) >= FLOW_HIGH)
tnc2->status |= TS_RXSTOP;
}
}
/* public routines for use by tnc2 emulator */
/* initialize TNC2 client port */
int
tnc2_init (tnc2)
register struct tnc *tnc2;
{
long sav_ssp;
char *sysbase;
tnc2->status = 0; /* Unbuffered, all OFF */
sav_ssp = Super(NULL); /* access system data */
sysbase = (char *) SYSBASE; /* find OS */
biosvers = *((unsigned int *) (sysbase + 2)); /* read BIOS version */
Super(sav_ssp);
switch (tnc2->dev)
{
case 0:
case 1:
case 3:
case 6:
case 7:
if (biosvers < 0x0102){
printf("devices 0-7 need BIOS 1.2 (Blitter-TOS)\n");
return 1;
}
if ((tnc2->input.begin = malloc(PIPEBUF)) == NULLCHAR){
printf(nospace);
return 1;
}
tnc2->input.in = tnc2->input.out = tnc2->input.begin;
tnc2->input.end = tnc2->input.begin + PIPEBUF;
tnc2->input.num = 0;
if ((tnc2->output.begin = malloc(PIPEBUF)) == NULLCHAR){
free(tnc2->input.begin);
printf(nospace);
return 1;
}
tnc2->output.in = tnc2->output.out = tnc2->output.begin;
tnc2->output.end = tnc2->output.begin + PIPEBUF;
tnc2->output.num = 0;
dev2tnc[tnc2->dev] = tnc2;
sav_ssp = Super(NULL); /* access system data */
tnc2->save_vec[0] = BCONSTAT[tnc2->dev]; /* save old handlers */
tnc2->save_vec[1] = BCONIN[tnc2->dev];
tnc2->save_vec[2] = BCOSTAT[tnc2->dev];
tnc2->save_vec[3] = BCONOUT[tnc2->dev];
BCONSTAT[tnc2->dev] = pconstat; /* set new handlers */
BCONIN[tnc2->dev] = pconin;
BCOSTAT[tnc2->dev] = pcostat;
BCONOUT[tnc2->dev] = pconout;
Super(sav_ssp);
break;
case 8:
Rsconf(1,0,0x88,0x01,0x01,0); /* 9600 baud, 8 bits, no parity */
break;
case 9:
sav_ssp = Super(NULL); /* access MIDI chip */
*((char *) 0xfffffc04L) = 0x03; /* RESET it */
*((char *) 0xfffffc04L) = 0x96; /* set 7812.5/9600 baud */
Super(sav_ssp);
break;
default:
printf("tnc2: unsupported device %d\n",tnc2->dev);
return 1;
}
return 0;
}
/* terminate TNC2 client port */
void
tnc2_term (tnc2)
register struct tnc *tnc2;
{
long sav_ssp;
switch (tnc2->dev)
{
case 0:
case 1:
case 3:
case 6:
case 7:
sav_ssp = Super(NULL); /* access system data */
BCONSTAT[tnc2->dev] = tnc2->save_vec[0]; /* restore old handlers */
BCONIN[tnc2->dev] = tnc2->save_vec[1];
BCOSTAT[tnc2->dev] = tnc2->save_vec[2];
BCONOUT[tnc2->dev] = tnc2->save_vec[3];
Super(sav_ssp);
dev2tnc[tnc2->dev] = NULLTNC;
free(tnc2->input.begin);
free(tnc2->output.begin);
break;
}
}
/* read character from client, return -1 if none ready */
int
tnc2_ichar (tnc2)
register struct tnc *tnc2;
{
char c;
switch (tnc2->dev)
{
case 0:
case 1:
case 3:
case 6:
case 7:
if (tnc2->status & TS_BREAK) { /* received a BREAK */
tnc2->status &= ~TS_BREAK;
return TCH_BREAK;
}
if (tnc2->input.num == 0) /* nothing in buffer? */
return TCH_NOCHAR;
c = *tnc2->input.out++;
if (tnc2->input.out == tnc2->input.end)
tnc2->input.out = tnc2->input.begin;
if (--(tnc2->input.num) < FLOW_LOW)
tnc2->status &= ~TS_RXSTOP;
return uchar(c);
case 8:
if (!Bconstat(1)) /* check RS232 (AUX) status */
break;
return uchar(Bconin(1)); /* read char from RS232 (AUX) */
case 9:
if (!Bconstat(3)) /* check MIDI status */
break;
return uchar(Bconin(3)); /* read char from MIDI */
}
return TCH_NOCHAR;
}
/* send character to client, return 0 when blocked */
/* when character is <0, only check if it is blocked */
int
tnc2_ochar (tnc2,c)
register struct tnc *tnc2;
int c;
{
int i;
switch (tnc2->dev)
{
case 0:
case 1:
case 3:
case 6:
case 7:
if (c < 0) { /* a status check */
if (tnc2->output.num < FLOW_LOW)
return 1;
/* maybe we better be conservative and don't allow him to go...
if (!(tnc2->status & TS_TXSTOP) && tnc2->output.num < FLOW_HIGH)
return 1; (he will try again later!) */
return 0;
}
if (tnc2->output.num == PIPEBUF) { /* buffer full? */
eihalt(); /* give a chance to read chars */
if (tnc2->output.num == PIPEBUF) { /* still no space? */
tnc2->status |= TS_TXOVR; /* transmitter overrun */
return 0;
}
}
*tnc2->output.in++ = c;
if (tnc2->output.in == tnc2->output.end)
tnc2->output.in = tnc2->output.begin;
if (++(tnc2->output.num) >= FLOW_HIGH)
tnc2->status |= TS_TXSTOP;
return 1;
case 8:
i = 50;
while (!Bcostat(1) && --i) /* when output buffer is full */
eihalt(); /* wait a short while */
if (i == 0) /* tried it, but still not ready */
break;
if (c >= 0)
Bconout(1,c); /* send char to RS232 (AUX) */
return 1;
case 9:
if (c >= 0)
Bconout(3,c); /* send char to MIDI */
return 1;
}
tnc2->status |= TS_TXOVR; /* transmitter overrun */
return 0;
}
/* set flowcontrol method for specified client */
/* method 1=soft (XON/XOFF) 2=hard (RTS/CTS) */
void
tnc2_flow (tnc2,method)
register struct tnc *tnc2;
int method;
{
switch (tnc2->dev)
{
case 0:
case 1:
case 3:
case 6:
case 7:
if (method & 1) /* soft control used to set TX buffer */
tnc2->status |= TS_TXBUF;
else
tnc2->status &= ~TS_TXBUF;
break;
case 8:
if (biosvers < 0x0102) /* when using old BIOS */
method &= ~2; /* hardware flowctrl does not work */
Rsconf(-1,method,-1,-1,-1,-1); /* set RS232 flow control method */
break;
}
}